/**
 * There are code generation
 */
package com.neusoft.lohas.modules.ivm.entity.product;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import org.hibernate.annotations.Where;
import org.hibernate.validator.constraints.Length;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Lists;
import com.neusoft.lohas.common.persistence.IdEntity;
import com.neusoft.lohas.common.utils.StringUtils;
import com.neusoft.lohas.modules.ivm.entity.merchant.Merchant;

/**
 * 商品信息Entity
 * 
 * @author Jackie.Liu
 * @version 2014-11-13
 */
@Entity
@Table(name = "ivm_product")
@DynamicInsert
@DynamicUpdate
public class Product extends IdEntity<Product> {

	private static final long serialVersionUID = 1L;
	private Long code;
	private Merchant merchant; //所属商户
	private String name; // 名称
	private String assisTitle; // 副标题
	private String logoUrl; // 商品图片
	private ProductClassify classify;
	private double price; // 单价（现价）
	private double marketPrice; //市场价
	private ProductUnit productUnit; // 销售单位
	private int stock; // 库存
	private double stockAmount; //当前库存余算金额
	private String openState; // 上架状态：1上架，0下架
	private int startSaleNum=1; // 起购量
	private int purchaseNum; // 限购量
	private String isPurchase; //是否限购
	private Date autoShelvesDate; // 自动上架时间
	private Date autoUnderDate; // 自动下架时间
	private Supplier defaultSupplier; //默认供应商
	private String shouldKnow; //购买须知
	private Integer sort; //排序
	private String cartId;
	private int number; //对应购物车里面该商品的购买数量
	private double amount; //对应购物车里面该商品的购买金额  
	private String spec; //商品规格
	private int specNum; //商品规格_数量
	private ProductUnit specUnit; //商品规格_单位  即采购单位
	private String toPay; //是否支持到付： 1是，0否
	private String effectiveTime; //购物车有效时间
	private String marketPriceTarget; //市场跟价对象
	private int collectPriceCycle; //摸价周期
	private String stockState; //库存状态：真实、虚拟
	private int normalNum; //真实库存_正常标准
	private int fillNum; //真实库存_补货标准
	private int lackNum; //真实库存_短缺标准
	private String purchaseDesc; //采购说明
	
	private double originalPrice; //原价
	private double tradePrice; //进价
	private int scan; //浏览次数
	private String proProperty="0"; //商品属性 0:实体商品,1虚拟商品
	private String gift; //新用户礼包，0：否，1：是
	
	private List<ProductClassify> classifyList = Lists.newArrayList(); // 分类列表
	private List<Supplier> supplierList = Lists.newArrayList(); //拥有的供应商列表
	private List<ProductInventoryDetail> inventoryDetailList = Lists.newArrayList(); //商品采购入库记录集合
	private List<ProductOutDetail> outDetailList = Lists.newArrayList(); //商品出库记录集合
	private List<ProductRelation> relationList = Lists.newArrayList(); //虚拟商品拥有的实体商品集合

	public Product() {
		super();
		this.sort = 30;
	}

	public Product(String id) {
		this();
		this.id = id;
	}

	public Long getCode() {
		return code;
	}

	public void setCode(Long code) {
		this.code = code;
	}

	@ManyToOne
	@JoinColumn(name="merchant_id")
	@NotFound(action = NotFoundAction.IGNORE)
	@NotNull(message="归属商户不能为空")
	public Merchant getMerchant() {
		return merchant;
	}

	public void setMerchant(Merchant merchant) {
		this.merchant = merchant;
	}

	@Length(min = 1, max = 200)
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAssisTitle() {
		return assisTitle;
	}

	public void setAssisTitle(String assisTitle) {
		this.assisTitle = assisTitle;
	}

	public String getLogoUrl() {
		return logoUrl;
	}

	public void setLogoUrl(String logoUrl) {
		this.logoUrl = logoUrl;
	}
	
	@ManyToOne
	@JoinColumn(name="classify_id")
	@NotFound(action = NotFoundAction.IGNORE)
//	@NotNull(message="归属商品一级分类不能为空")
	public ProductClassify getClassify() {
		return classify;
	}

	public void setClassify(ProductClassify classify) {
		this.classify = classify;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public double getMarketPrice() {
		return marketPrice;
	}

	public void setMarketPrice(double marketPrice) {
		this.marketPrice = marketPrice;
	}

	@ManyToOne
	@JoinColumn(name="unit_id")
	@NotFound(action = NotFoundAction.IGNORE)
	public ProductUnit getProductUnit() {
		return productUnit;
	}

	public void setProductUnit(ProductUnit productUnit) {
		this.productUnit = productUnit;
	}

	public int getStock() {
		return stock;
	}

	public void setStock(int stock) {
		this.stock = stock;
	}

	public double getStockAmount() {
		return stockAmount;
	}

	public void setStockAmount(double stockAmount) {
		this.stockAmount = stockAmount;
	}

	public String getOpenState() {
		return openState;
	}

	public void setOpenState(String openState) {
		this.openState = openState;
	}

	public int getStartSaleNum() {
		return startSaleNum;
	}

	public void setStartSaleNum(int startSaleNum) {
		this.startSaleNum = startSaleNum;
	}

	public int getPurchaseNum() {
		return purchaseNum;
	}

	public void setPurchaseNum(int purchaseNum) {
		this.purchaseNum = purchaseNum;
	}
	
	@Transient
	public String getIsPurchase() {
		return isPurchase;
	}

	public void setIsPurchase(String isPurchase) {
		this.isPurchase = isPurchase;
	}

	public Date getAutoShelvesDate() {
		return autoShelvesDate;
	}

	public void setAutoShelvesDate(Date autoShelvesDate) {
		this.autoShelvesDate = autoShelvesDate;
	}

	public Date getAutoUnderDate() {
		return autoUnderDate;
	}

	public void setAutoUnderDate(Date autoUnderDate) {
		this.autoUnderDate = autoUnderDate;
	}
	
	@ManyToOne
	@JoinColumn(name="default_supplier_id")
	@NotFound(action = NotFoundAction.IGNORE)
	public Supplier getDefaultSupplier() {
		return defaultSupplier;
	}

	public void setDefaultSupplier(Supplier defaultSupplier) {
		this.defaultSupplier = defaultSupplier;
	}

	public String getShouldKnow() {
		return shouldKnow;
	}

	public void setShouldKnow(String shouldKnow) {
		this.shouldKnow = shouldKnow;
	}

	@NotNull
	public Integer getSort() {
		return sort;
	}

	public void setSort(Integer sort) {
		this.sort = sort;
	}

	@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
	@JoinTable(name = "ivm_relationship_product_classify", joinColumns = { @JoinColumn(name = "product_id") }, inverseJoinColumns = { @JoinColumn(name = "classify_id") })
	@Where(clause="del_flag='"+DEL_FLAG_NORMAL+"'")
	@OrderBy("id") @Fetch(FetchMode.SUBSELECT)
	@NotFound(action = NotFoundAction.IGNORE)
	@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
	@JsonIgnore
	public List<ProductClassify> getClassifyList() {
		return classifyList;
	}

	public void setClassifyList(List<ProductClassify> classifyList) {
		this.classifyList = classifyList;
	}

	@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
	@JoinTable(name = "ivm_supplier_product", joinColumns = { @JoinColumn(name = "product_id") }, inverseJoinColumns = { @JoinColumn(name = "supplier_id") })
	@Where(clause="del_flag='"+DEL_FLAG_NORMAL+"'")
	@OrderBy("id") @Fetch(FetchMode.SUBSELECT)
	@NotFound(action = NotFoundAction.IGNORE)
	@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
	@JsonIgnore
	public List<Supplier> getSupplierList() {
		return supplierList;
	}

	public void setSupplierList(List<Supplier> supplierList) {
		this.supplierList = supplierList;
	}
	
	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "product")
	@Where(clause="del_flag='"+DEL_FLAG_NORMAL+"'")
	@OrderBy("create_date")
	@NotFound(action = NotFoundAction.IGNORE)
	@JsonIgnore
	public List<ProductInventoryDetail> getInventoryDetailList() {
		return inventoryDetailList;
	}

	public void setInventoryDetailList(
			List<ProductInventoryDetail> inventoryDetailList) {
		this.inventoryDetailList = inventoryDetailList;
	}

	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "product")
	@Where(clause="del_flag='"+DEL_FLAG_NORMAL+"'")
	@OrderBy("create_date")
	@NotFound(action = NotFoundAction.IGNORE)
	@JsonIgnore
	public List<ProductOutDetail> getOutDetailList() {
		return outDetailList;
	}

	public void setOutDetailList(List<ProductOutDetail> outDetailList) {
		this.outDetailList = outDetailList;
	}

	@Transient
	@JsonIgnore
	public List<String> getSupplierIdList() {
		List<String> supplierIdList = Lists.newArrayList();
		for (Supplier supplier : supplierList) {
			supplierIdList.add(supplier.getId());
		}
		return supplierIdList;
	}

	@Transient
	public void setSupplierIdList(List<String> supplierIdList) {
		supplierList = Lists.newArrayList();
		if(supplierIdList==null) return;
		for (String supplierId : supplierIdList) {
			Supplier supplier = new Supplier();
			supplier.setId(supplierId);
			supplierList.add(supplier);
		}
	}

	@Transient
	@JsonIgnore
	public List<String> getClassifyIdList() {
		List<String> classifyIdList = Lists.newArrayList();
		for (ProductClassify classify : classifyList) {
			classifyIdList.add(classify.getId());
		}
		return classifyIdList;
	}

	@Transient
	public void setClassifyIdList(List<String> classifyIdList) {
		classifyList = Lists.newArrayList();
		if(classifyIdList==null) return;
		for (String classifyId : classifyIdList) {
			ProductClassify classify = new ProductClassify();
			classify.setId(classifyId);
			classifyList.add(classify);
		}
	}
	
	/**
	 * 商品用户的分类名称字符串, 多个分类名称用','分隔.
	 */
	@Transient
	public String getClassifyNames() {
		if (classifyList.size()>0) {
			Map<String, String> map = new LinkedHashMap<String, String>();
			for (ProductClassify bean : classifyList) {
				if (map.containsKey(bean.getParent().getName())) {
					map.put(bean.getParent().getName(), map.get(bean.getParent().getName())+","+bean.getName());
				}else {
					map.put(bean.getParent().getName(), bean.getParent().getName()+":"+bean.getName());
				}
			}
			StringBuffer rtn = new StringBuffer();
			int i = 0;
			for (String string : map.values()) {
				if (i==map.size()-1) {
					rtn.append(string);
				}else {
					rtn.append(string+"<br/>");
				}
			}
			return rtn.toString();
		}
		return null;
	}
	
	/**
	 * 购物车里对应该商品的编号
	 * @return
	 */
	@Transient
	public String getCartId() {
		return cartId;
	}

	public void setCartId(String cartId) {
		this.cartId = cartId;
	}

	/**
	 * 购物车里对应该商品的购买数量
	 * @return
	 */
	@Transient
	public int getNumber(){
		return number;
	}
	
	public void setNumber(int number){
		this.number = number;
	}

	/**
	 * 购物车里对应该商品的购买金额
	 * @return
	 */
	@Transient
	public double getAmount() {
		return amount;
	}

	public void setAmount(double amount) {
		this.amount = amount;
	}

	public String getSpec() {
		return spec;
	}

	public void setSpec(String spec) {
		this.spec = spec;
	}

	public int getSpecNum() {
		return specNum;
	}

	public void setSpecNum(int specNum) {
		this.specNum = specNum;
	}
	
	@ManyToOne
	@JoinColumn(name="spec_unit")
	@NotFound(action = NotFoundAction.IGNORE)
	public ProductUnit getSpecUnit() {
		return specUnit;
	}

	public void setSpecUnit(ProductUnit specUnit) {
		this.specUnit = specUnit;
	}

	public String getToPay() {
		return toPay;
	}

	public void setToPay(String toPay) {
		this.toPay = toPay;
	}

	public String getEffectiveTime() {
		if(!StringUtils.isNotBlank(this.effectiveTime)){
			return "24";
		}
		return effectiveTime;
	}

	public void setEffectiveTime(String effectiveTime) {
		this.effectiveTime = effectiveTime;
	}

	public String getMarketPriceTarget() {
		return marketPriceTarget;
	}

	public void setMarketPriceTarget(String marketPriceTarget) {
		this.marketPriceTarget = marketPriceTarget;
	}

	public int getCollectPriceCycle() {
		return collectPriceCycle;
	}

	public void setCollectPriceCycle(int collectPriceCycle) {
		this.collectPriceCycle = collectPriceCycle;
	}

	public String getStockState() {
		return stockState;
	}

	public void setStockState(String stockState) {
		this.stockState = stockState;
	}

	public int getNormalNum() {
		return normalNum;
	}

	public void setNormalNum(int normalNum) {
		this.normalNum = normalNum;
	}

	public int getFillNum() {
		return fillNum;
	}

	public void setFillNum(int fillNum) {
		this.fillNum = fillNum;
	}

	public int getLackNum() {
		return lackNum;
	}

	public void setLackNum(int lackNum) {
		this.lackNum = lackNum;
	}

	public String getPurchaseDesc() {
		return purchaseDesc;
	}

	public void setPurchaseDesc(String purchaseDesc) {
		this.purchaseDesc = purchaseDesc;
	}

	public double getOriginalPrice() {
		return originalPrice;
	}

	public void setOriginalPrice(double originalPrice) {
		this.originalPrice = originalPrice;
	}

	public double getTradePrice() {
		return tradePrice;
	}

	public void setTradePrice(double tradePrice) {
		this.tradePrice = tradePrice;
	}
	
	public int getScan() {
		return scan;
	}

	public void setScan(int scan) {
		this.scan = scan;
	}

	/**
	 * 获取商品耗损率
	 * 耗损数量/入库总量
	 */
	@Transient
	public Double getLossRate() {
		int intoAmount = 0;
		int outAmount = 0;
		for(ProductInventoryDetail intoDetail:this.inventoryDetailList){
			intoAmount += intoDetail.getWinWeight();
		}
		for(ProductOutDetail outDetail:this.outDetailList){
			if(!outDetail.getType().equals("0")){
				outAmount += outDetail.getWeight();
			}
		}
		if(outAmount==0){
			return 0.0;
		}
		double rate = outAmount/(intoAmount*1.00);
		return rate;
	}
	
	/**
	 * 获取商品售出数量
	 * 出库类型为1的总量
	 */
	@Transient
	public int getSaleNum(){
		int num = 0;
		for(ProductOutDetail outDetail:this.outDetailList){
			if(outDetail.getType().equals("0")){
				num += outDetail.getNumber();
			}
		}
		return num;
	}

	public String getProProperty() {
		return proProperty;
	}

	public void setProProperty(String proProperty) {
		this.proProperty = proProperty;
	}

	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "parent")
	@Where(clause="del_flag='"+DEL_FLAG_NORMAL+"'")
	@OrderBy("create_date")
	@NotFound(action = NotFoundAction.IGNORE)
	@JsonIgnore
	public List<ProductRelation> getRelationList() {
		return relationList;
	}

	public void setRelationList(List<ProductRelation> relationList) {
		this.relationList = relationList;
	}

	public String getGift() {
		return gift;
	}

	public void setGift(String gift) {
		this.gift = gift;
	}

}
